{
 "cells": [
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T07:19:02.249569Z",
     "start_time": "2025-02-27T07:18:59.094208Z"
    }
   },
   "source": [
    "import matplotlib as mpl\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "import numpy as np\n",
    "import sklearn\n",
    "import pandas as pd\n",
    "import os\n",
    "import sys\n",
    "import time\n",
    "from tqdm.auto import tqdm\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "\n",
    "print(sys.version_info)\n",
    "for module in mpl, np, pd, sklearn, torch:\n",
    "    print(module.__name__, module.__version__)\n",
    "    \n",
    "device = torch.device(\"cuda:0\") if torch.cuda.is_available() else torch.device(\"cpu\")\n",
    "print(device)\n",
    "\n",
    "seed = 42\n"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "sys.version_info(major=3, minor=12, micro=3, releaselevel='final', serial=0)\n",
      "matplotlib 3.10.0\n",
      "numpy 2.0.2\n",
      "pandas 2.2.3\n",
      "sklearn 1.6.1\n",
      "torch 2.6.0+cu126\n",
      "cuda:0\n"
     ]
    }
   ],
   "execution_count": 1
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 数据准备"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T07:19:04.279730Z",
     "start_time": "2025-02-27T07:19:02.250560Z"
    }
   },
   "source": [
    "from torchvision import datasets\n",
    "from torchvision.transforms import ToTensor\n",
    "from torch.utils.data import random_split\n",
    "\n",
    "# fashion_mnist图像分类数据集\n",
    "train_ds = datasets.FashionMNIST(\n",
    "    root=\"data\",\n",
    "    train=True,\n",
    "    download=True,\n",
    "    transform=ToTensor()\n",
    ")\n",
    "\n",
    "test_ds = datasets.FashionMNIST(\n",
    "    root=\"data\",\n",
    "    train=False,\n",
    "    download=True,\n",
    "    transform=ToTensor()\n",
    ")\n",
    "\n",
    "# torchvision 数据集里没有提供训练集和验证集的划分\n",
    "# 这里用 random_split 按照 11 : 1 的比例来划分数据集\n",
    "train_ds, val_ds = random_split(train_ds, [55000, 5000], torch.Generator().manual_seed(seed))"
   ],
   "outputs": [],
   "execution_count": 2
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T07:19:04.283816Z",
     "start_time": "2025-02-27T07:19:04.280726Z"
    }
   },
   "source": [
    "from torchvision.transforms import Normalize\n",
    "\n",
    "# 遍历train_ds得到每张图片，计算每个通道的均值和方差\n",
    "def cal_mean_std(ds):\n",
    "    mean = 0.\n",
    "    std = 0.\n",
    "    for img, _ in ds:\n",
    "        mean += img.mean(dim=(1, 2))\n",
    "        std += img.std(dim=(1, 2))\n",
    "    mean /= len(ds)\n",
    "    std /= len(ds)\n",
    "    return mean, std\n",
    "\n",
    "\n",
    "# print(cal_mean_std(train_ds))\n",
    "# 0.2860， 0.3205\n",
    "transforms = nn.Sequential(\n",
    "    Normalize([0.2856], [0.3202])\n",
    ")"
   ],
   "outputs": [],
   "execution_count": 3
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T07:19:04.299814Z",
     "start_time": "2025-02-27T07:19:04.283816Z"
    }
   },
   "source": [
    "from torch.utils.data.dataloader import DataLoader\n",
    "\n",
    "batch_size = 32\n",
    "# 从数据集到dataloader\n",
    "train_loader = DataLoader(train_ds, batch_size=batch_size, shuffle=True, num_workers=4)\n",
    "val_loader = DataLoader(val_ds, batch_size=batch_size, shuffle=False, num_workers=4)\n",
    "test_loader = DataLoader(test_ds, batch_size=batch_size, shuffle=False, num_workers=4)"
   ],
   "outputs": [],
   "execution_count": 4
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 定义模型\n",
    "\n",
    "使用深度可分离的卷积\n",
    "\n",
    "pytorch需要自行实现"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T07:19:04.304418Z",
     "start_time": "2025-02-27T07:19:04.300812Z"
    }
   },
   "source": [
    "# 定义深度可分离卷积层，torch没有实现，tf有实现\n",
    "class DepthWiseConv2d(nn.Module):\n",
    "    def __init__(self, in_channels, out_channels, kernel_size, stride=1, padding=0, bias=True):\n",
    "        super(DepthWiseConv2d, self).__init__() #这里写为super().__init__()，等价的\n",
    "        self.depthwise_conv = nn.Conv2d(in_channels, in_channels, kernel_size, stride, padding, groups=in_channels, bias=False) #groups参数表示一个卷积核的每个通道分别进行运算\n",
    "        self.pointwise_conv = nn.Conv2d(in_channels, out_channels, 1, 1, 0, bias=bias)\n",
    "    \n",
    "    def forward(self, x):\n",
    "        x = self.depthwise_conv(x)\n",
    "        x = self.pointwise_conv(x)\n",
    "        return x"
   ],
   "outputs": [],
   "execution_count": 5
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T07:19:04.317265Z",
     "start_time": "2025-02-27T07:19:04.305415Z"
    }
   },
   "source": [
    "\n",
    "class CNN(nn.Module):\n",
    "    def __init__(self, activation=\"relu\"):\n",
    "        super(CNN, self).__init__()\n",
    "        self.activation = F.relu if activation == \"relu\" else F.selu\n",
    "        self.conv1 = nn.Conv2d(in_channels=1, out_channels=32, kernel_size=3, padding=\"same\")\n",
    "        self.conv2 = DepthWiseConv2d(in_channels=32, out_channels=32, kernel_size=3, padding=\"same\")\n",
    "        self.pool = nn.MaxPool2d(2, 2)\n",
    "        self.conv3 = DepthWiseConv2d(in_channels=32, out_channels=64, kernel_size=3, padding=\"same\")\n",
    "        self.conv4 = DepthWiseConv2d(in_channels=64, out_channels=64, kernel_size=3, padding=\"same\")\n",
    "        self.conv5 = DepthWiseConv2d(in_channels=64, out_channels=128, kernel_size=3, padding=\"same\")\n",
    "        self.conv6 = DepthWiseConv2d(in_channels=128, out_channels=128, kernel_size=3, padding=\"same\")\n",
    "        self.flatten = nn.Flatten()\n",
    "        # input shape is (28, 28, 1) so the fc1 layer in_features is 128 * 3 * 3\n",
    "        self.fc1 = nn.Linear(128 * 3 * 3, 128)\n",
    "        self.fc2 = nn.Linear(128, 10)\n",
    "        \n",
    "        self.init_weights()\n",
    "        \n",
    "    def init_weights(self):\n",
    "        \"\"\"使用 xavier 均匀分布来初始化全连接层、卷积层的权重 W\"\"\"\n",
    "        for m in self.modules():\n",
    "            if isinstance(m, (nn.Linear, nn.Conv2d)):\n",
    "                nn.init.xavier_uniform_(m.weight)\n",
    "                if m.bias is not None:\n",
    "                    nn.init.zeros_(m.bias)\n",
    "        \n",
    "    def forward(self, x):\n",
    "        act = self.activation\n",
    "        #x -->(batch_size, 1, 28, 28)\n",
    "        x = self.pool(act(self.conv2(act(self.conv1(x)))))  # (batch_size, 32, 14, 14)\n",
    "        x = self.pool(act(self.conv4(act(self.conv3(x)))))  # (batch_size, 64, 7, 7)\n",
    "        x = self.pool(act(self.conv6(act(self.conv5(x)))))  # (batch_size, 128, 3, 3)\n",
    "        x = self.flatten(x) # (batch_size, 128 * 3 * 3)\n",
    "        x = act(self.fc1(x)) # (batch_size, 128)\n",
    "        x = self.fc2(x) # (batch_size, 10)\n",
    "        return x\n",
    "    \n",
    "\n",
    "for idx, (key, value) in enumerate(CNN().named_parameters()):\n",
    "    print(f\"{key}\\tparamerters num: {np.prod(value.shape)}\")\n"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "conv1.weight\tparamerters num: 288\n",
      "conv1.bias\tparamerters num: 32\n",
      "conv2.depthwise_conv.weight\tparamerters num: 288\n",
      "conv2.pointwise_conv.weight\tparamerters num: 1024\n",
      "conv2.pointwise_conv.bias\tparamerters num: 32\n",
      "conv3.depthwise_conv.weight\tparamerters num: 288\n",
      "conv3.pointwise_conv.weight\tparamerters num: 2048\n",
      "conv3.pointwise_conv.bias\tparamerters num: 64\n",
      "conv4.depthwise_conv.weight\tparamerters num: 576\n",
      "conv4.pointwise_conv.weight\tparamerters num: 4096\n",
      "conv4.pointwise_conv.bias\tparamerters num: 64\n",
      "conv5.depthwise_conv.weight\tparamerters num: 576\n",
      "conv5.pointwise_conv.weight\tparamerters num: 8192\n",
      "conv5.pointwise_conv.bias\tparamerters num: 128\n",
      "conv6.depthwise_conv.weight\tparamerters num: 1152\n",
      "conv6.pointwise_conv.weight\tparamerters num: 16384\n",
      "conv6.pointwise_conv.bias\tparamerters num: 128\n",
      "fc1.weight\tparamerters num: 147456\n",
      "fc1.bias\tparamerters num: 128\n",
      "fc2.weight\tparamerters num: 1280\n",
      "fc2.bias\tparamerters num: 10\n"
     ]
    }
   ],
   "execution_count": 6
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T07:19:04.325587Z",
     "start_time": "2025-02-27T07:19:04.318223Z"
    }
   },
   "cell_type": "code",
   "source": [
    "def count_parameters(model): #计算模型总参数量\n",
    "    return sum(p.numel() for p in model.parameters() if p.requires_grad)\n",
    "count_parameters(CNN())"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "184234"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 7
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T07:19:04.329793Z",
     "start_time": "2025-02-27T07:19:04.325587Z"
    }
   },
   "cell_type": "code",
   "source": "288 + 288 +288+ 1024 + 2048 + 576 +576+ 4096+ 8192 + 1152 + 16384 + 147456 + 1280",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "183648"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 8
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T07:19:04.333527Z",
     "start_time": "2025-02-27T07:19:04.329793Z"
    }
   },
   "cell_type": "code",
   "source": "32 + 32 + 64 + 64 + 128 + 128 +128+ 10",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "586"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 9
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T07:19:04.337229Z",
     "start_time": "2025-02-27T07:19:04.333527Z"
    }
   },
   "cell_type": "code",
   "source": "183648+586",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "184234"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 10
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 训练\n",
    "\n",
    "pytorch的训练需要自行实现，包括\n",
    "1. 定义损失函数\n",
    "2. 定义优化器\n",
    "3. 定义训练步\n",
    "4. 训练"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T07:19:04.389089Z",
     "start_time": "2025-02-27T07:19:04.338227Z"
    }
   },
   "source": [
    "from sklearn.metrics import accuracy_score\n",
    "\n",
    "@torch.no_grad()\n",
    "def evaluating(model, dataloader, loss_fct):\n",
    "    loss_list = []\n",
    "    pred_list = []\n",
    "    label_list = []\n",
    "    for datas, labels in dataloader:\n",
    "        datas = datas.to(device)\n",
    "        labels = labels.to(device)\n",
    "        # 前向计算\n",
    "        logits = model(datas)\n",
    "        loss = loss_fct(logits, labels)         # 验证集损失\n",
    "        loss_list.append(loss.item())\n",
    "        \n",
    "        preds = logits.argmax(axis=-1)    # 验证集预测\n",
    "        pred_list.extend(preds.cpu().numpy().tolist())\n",
    "        label_list.extend(labels.cpu().numpy().tolist())\n",
    "        \n",
    "    acc = accuracy_score(label_list, pred_list)\n",
    "    return np.mean(loss_list), acc\n"
   ],
   "outputs": [],
   "execution_count": 11
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### TensorBoard 可视化\n",
    "\n",
    "\n",
    "训练过程中可以使用如下命令启动tensorboard服务。\n",
    "\n",
    "```shell\n",
    "tensorboard \\\n",
    "    --logdir=runs \\     # log 存放路径\n",
    "    --host 0.0.0.0 \\    # ip\n",
    "    --port 8848         # 端口\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T07:19:07.290654Z",
     "start_time": "2025-02-27T07:19:04.390087Z"
    }
   },
   "source": [
    "from torch.utils.tensorboard import SummaryWriter\n",
    "\n",
    "\n",
    "class TensorBoardCallback:\n",
    "    def __init__(self, log_dir, flush_secs=10):\n",
    "        \"\"\"\n",
    "        Args:\n",
    "            log_dir (str): dir to write log.\n",
    "            flush_secs (int, optional): write to dsk each flush_secs seconds. Defaults to 10.\n",
    "        \"\"\"\n",
    "        self.writer = SummaryWriter(log_dir=log_dir, flush_secs=flush_secs)\n",
    "\n",
    "    def draw_model(self, model, input_shape):\n",
    "        self.writer.add_graph(model, input_to_model=torch.randn(input_shape))\n",
    "        \n",
    "    def add_loss_scalars(self, step, loss, val_loss):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/loss\", \n",
    "            tag_scalar_dict={\"loss\": loss, \"val_loss\": val_loss},\n",
    "            global_step=step,\n",
    "            )\n",
    "        \n",
    "    def add_acc_scalars(self, step, acc, val_acc):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/accuracy\",\n",
    "            tag_scalar_dict={\"accuracy\": acc, \"val_accuracy\": val_acc},\n",
    "            global_step=step,\n",
    "        )\n",
    "        \n",
    "    def add_lr_scalars(self, step, learning_rate):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/learning_rate\",\n",
    "            tag_scalar_dict={\"learning_rate\": learning_rate},\n",
    "            global_step=step,\n",
    "            \n",
    "        )\n",
    "    \n",
    "    def __call__(self, step, **kwargs):\n",
    "        # add loss\n",
    "        loss = kwargs.pop(\"loss\", None)\n",
    "        val_loss = kwargs.pop(\"val_loss\", None)\n",
    "        if loss is not None and val_loss is not None:\n",
    "            self.add_loss_scalars(step, loss, val_loss)\n",
    "        # add acc\n",
    "        acc = kwargs.pop(\"acc\", None)\n",
    "        val_acc = kwargs.pop(\"val_acc\", None)\n",
    "        if acc is not None and val_acc is not None:\n",
    "            self.add_acc_scalars(step, acc, val_acc)\n",
    "        # add lr\n",
    "        learning_rate = kwargs.pop(\"lr\", None)\n",
    "        if learning_rate is not None:\n",
    "            self.add_lr_scalars(step, learning_rate)\n"
   ],
   "outputs": [],
   "execution_count": 12
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Save Best\n"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T07:19:07.295158Z",
     "start_time": "2025-02-27T07:19:07.291162Z"
    }
   },
   "source": [
    "class SaveCheckpointsCallback:\n",
    "    def __init__(self, save_dir, save_step=5000, save_best_only=True):\n",
    "        \"\"\"\n",
    "        Save checkpoints each save_epoch epoch. \n",
    "        We save checkpoint by epoch in this implementation.\n",
    "        Usually, training scripts with pytorch evaluating model and save checkpoint by step.\n",
    "\n",
    "        Args:\n",
    "            save_dir (str): dir to save checkpoint\n",
    "            save_epoch (int, optional): the frequency to save checkpoint. Defaults to 1.\n",
    "            save_best_only (bool, optional): If True, only save the best model or save each model at every epoch.\n",
    "        \"\"\"\n",
    "        self.save_dir = save_dir\n",
    "        self.save_step = save_step\n",
    "        self.save_best_only = save_best_only\n",
    "        self.best_metrics = -1\n",
    "        \n",
    "        # mkdir\n",
    "        if not os.path.exists(self.save_dir):\n",
    "            os.mkdir(self.save_dir)\n",
    "        \n",
    "    def __call__(self, step, state_dict, metric=None):\n",
    "        if step % self.save_step > 0:\n",
    "            return\n",
    "        \n",
    "        if self.save_best_only:\n",
    "            assert metric is not None\n",
    "            if metric >= self.best_metrics:\n",
    "                # save checkpoints\n",
    "                torch.save(state_dict, os.path.join(self.save_dir, \"best.ckpt\"))\n",
    "                # update best metrics\n",
    "                self.best_metrics = metric\n",
    "        else:\n",
    "            torch.save(state_dict, os.path.join(self.save_dir, f\"{step}.ckpt\"))\n",
    "\n"
   ],
   "outputs": [],
   "execution_count": 13
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Early Stop"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T07:19:07.314720Z",
     "start_time": "2025-02-27T07:19:07.295158Z"
    }
   },
   "source": [
    "class EarlyStopCallback:\n",
    "    def __init__(self, patience=5, min_delta=0.01):\n",
    "        \"\"\"\n",
    "\n",
    "        Args:\n",
    "            patience (int, optional): Number of epochs with no improvement after which training will be stopped.. Defaults to 5.\n",
    "            min_delta (float, optional): Minimum change in the monitored quantity to qualify as an improvement, i.e. an absolute \n",
    "                change of less than min_delta, will count as no improvement. Defaults to 0.01.\n",
    "        \"\"\"\n",
    "        self.patience = patience\n",
    "        self.min_delta = min_delta\n",
    "        self.best_metric = -1\n",
    "        self.counter = 0\n",
    "        \n",
    "    def __call__(self, metric):\n",
    "        if metric >= self.best_metric + self.min_delta:\n",
    "            # update best metric\n",
    "            self.best_metric = metric\n",
    "            # reset counter \n",
    "            self.counter = 0\n",
    "        else: \n",
    "            self.counter += 1\n",
    "            \n",
    "    @property\n",
    "    def early_stop(self):\n",
    "        return self.counter >= self.patience\n"
   ],
   "outputs": [],
   "execution_count": 14
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T07:28:37.748196Z",
     "start_time": "2025-02-27T07:19:07.315717Z"
    }
   },
   "source": [
    "# 训练\n",
    "def training(\n",
    "    model, \n",
    "    train_loader, \n",
    "    val_loader, \n",
    "    epoch, \n",
    "    loss_fct, \n",
    "    optimizer, \n",
    "    tensorboard_callback=None,\n",
    "    save_ckpt_callback=None,\n",
    "    early_stop_callback=None,\n",
    "    eval_step=500,\n",
    "    ):\n",
    "    record_dict = {\n",
    "        \"train\": [],\n",
    "        \"val\": []\n",
    "    }\n",
    "    \n",
    "    global_step = 0\n",
    "    model.train()\n",
    "    with tqdm(total=epoch * len(train_loader)) as pbar:\n",
    "        for epoch_id in range(epoch):\n",
    "            # training\n",
    "            for datas, labels in train_loader:\n",
    "                datas = datas.to(device)\n",
    "                labels = labels.to(device)\n",
    "                # 梯度清空\n",
    "                optimizer.zero_grad()\n",
    "                # 模型前向计算\n",
    "                logits = model(datas)\n",
    "                # 计算损失\n",
    "                loss = loss_fct(logits, labels)\n",
    "                # 梯度回传\n",
    "                loss.backward()\n",
    "                # 调整优化器，包括学习率的变动等\n",
    "                optimizer.step()\n",
    "                preds = logits.argmax(axis=-1)\n",
    "            \n",
    "                acc = accuracy_score(labels.cpu().numpy(), preds.cpu().numpy())    \n",
    "                loss = loss.cpu().item()\n",
    "                # record\n",
    "                \n",
    "                record_dict[\"train\"].append({\n",
    "                    \"loss\": loss, \"acc\": acc, \"step\": global_step\n",
    "                })\n",
    "                \n",
    "                # evaluating\n",
    "                if global_step % eval_step == 0:\n",
    "                    model.eval()\n",
    "                    val_loss, val_acc = evaluating(model, val_loader, loss_fct)\n",
    "                    record_dict[\"val\"].append({\n",
    "                        \"loss\": val_loss, \"acc\": val_acc, \"step\": global_step\n",
    "                    })\n",
    "                    model.train()\n",
    "                    \n",
    "                    # 1. 使用 tensorboard 可视化\n",
    "                    if tensorboard_callback is not None:\n",
    "                        tensorboard_callback(\n",
    "                            global_step, \n",
    "                            loss=loss, val_loss=val_loss,\n",
    "                            acc=acc, val_acc=val_acc,\n",
    "                            lr=optimizer.param_groups[0][\"lr\"],\n",
    "                            )\n",
    "                    \n",
    "                    # 2. 保存模型权重 save model checkpoint\n",
    "                    if save_ckpt_callback is not None:\n",
    "                        save_ckpt_callback(global_step, model.state_dict(), metric=val_acc)\n",
    "\n",
    "                    # 3. 早停 Early Stop\n",
    "                    if early_stop_callback is not None:\n",
    "                        early_stop_callback(val_acc)\n",
    "                        if early_stop_callback.early_stop:\n",
    "                            print(f\"Early stop at epoch {epoch_id} / global_step {global_step}\")\n",
    "                            return record_dict\n",
    "                    \n",
    "                # udate step\n",
    "                global_step += 1\n",
    "                pbar.update(1)\n",
    "                pbar.set_postfix({\"epoch\": epoch_id})\n",
    "        \n",
    "    return record_dict\n",
    "        \n",
    "\n",
    "epoch = 20\n",
    "\n",
    "activation = \"selu\"\n",
    "model = CNN(activation)\n",
    "\n",
    "# 1. 定义损失函数 采用交叉熵损失\n",
    "loss_fct = nn.CrossEntropyLoss()\n",
    "# 2. 定义优化器 采用SGD\n",
    "# Optimizers specified in the torch.optim package\n",
    "optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)\n",
    "\n",
    "# 1. tensorboard 可视化\n",
    "if not os.path.exists(\"runs\"):\n",
    "    os.mkdir(\"runs\")\n",
    "tensorboard_callback = TensorBoardCallback(f\"runs/dsc-{activation}\")\n",
    "tensorboard_callback.draw_model(model, [1, 1, 28, 28])\n",
    "# 2. save best\n",
    "if not os.path.exists(\"checkpoints\"):\n",
    "    os.makedirs(\"checkpoints\")\n",
    "save_ckpt_callback = SaveCheckpointsCallback(f\"checkpoints/dsc-{activation}\", save_step=len(train_loader), save_best_only=True)\n",
    "# 3. early stop\n",
    "early_stop_callback = EarlyStopCallback(patience=10)\n",
    "\n",
    "model = model.to(device)\n",
    "record = training(\n",
    "    model, \n",
    "    train_loader, \n",
    "    val_loader, \n",
    "    epoch, \n",
    "    loss_fct, \n",
    "    optimizer, \n",
    "    tensorboard_callback=None,\n",
    "    save_ckpt_callback=save_ckpt_callback,\n",
    "    early_stop_callback=early_stop_callback,\n",
    "    eval_step=len(train_loader)\n",
    "    )"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "  0%|          | 0/34380 [00:00<?, ?it/s]"
      ],
      "application/vnd.jupyter.widget-view+json": {
       "version_major": 2,
       "version_minor": 0,
       "model_id": "1aa5303282634158bcee4e1cb03ff8e8"
      }
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 15
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T07:28:37.932889Z",
     "start_time": "2025-02-27T07:28:37.749194Z"
    }
   },
   "source": [
    "#画线要注意的是损失是不一定在零到1之间的\n",
    "def plot_learning_curves(record_dict, sample_step=500):\n",
    "    # build DataFrame\n",
    "    train_df = pd.DataFrame(record_dict[\"train\"]).set_index(\"step\").iloc[::sample_step]\n",
    "    val_df = pd.DataFrame(record_dict[\"val\"]).set_index(\"step\")\n",
    "\n",
    "    # plot\n",
    "    fig_num = len(train_df.columns)\n",
    "    fig, axs = plt.subplots(1, fig_num, figsize=(5 * fig_num, 5))\n",
    "    for idx, item in enumerate(train_df.columns):    \n",
    "        axs[idx].plot(train_df.index, train_df[item], label=f\"train_{item}\")\n",
    "        axs[idx].plot(val_df.index, val_df[item], label=f\"val_{item}\")\n",
    "        axs[idx].grid()\n",
    "        axs[idx].legend()\n",
    "        axs[idx].set_xticks(range(0, train_df.index[-1], 5000))\n",
    "        axs[idx].set_xticklabels(map(lambda x: f\"{int(x/1000)}k\", range(0, train_df.index[-1], 5000)))\n",
    "        axs[idx].set_xlabel(\"step\")\n",
    "    \n",
    "    plt.show()\n",
    "\n",
    "plot_learning_curves(record, sample_step=500)  #横坐标是 steps"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Figure size 1000x500 with 2 Axes>"
      ],
      "image/png": "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"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 16
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 评估"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T07:28:43.483342Z",
     "start_time": "2025-02-27T07:28:37.933885Z"
    }
   },
   "source": [
    "# dataload for evaluating\n",
    "\n",
    "# load checkpoints\n",
    "model.load_state_dict(torch.load(f\"checkpoints/dsc-{activation}/best.ckpt\", weights_only=True,map_location=\"cpu\"))\n",
    "\n",
    "model.eval()\n",
    "loss, acc = evaluating(model, test_loader, loss_fct)\n",
    "print(f\"loss:     {loss:.4f}\\naccuracy: {acc:.4f}\")"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "loss:     0.3682\n",
      "accuracy: 0.8651\n"
     ]
    }
   ],
   "execution_count": 17
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "pytorch",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.8"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
